package com.zone.mybatis.session.defaults;

import com.zone.mybatis.executor.Executor;
import com.zone.mybatis.mapping.MappedStatement;
import com.zone.mybatis.session.Configuration;
import com.zone.mybatis.session.SqlSession;

import java.lang.reflect.Method;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: zongzi
 * @description: TODO
 * @date: 2023/12/17
 */
public class DefaultSqlSession implements SqlSession {
    private final Configuration configuration;

    private final Executor executor;

    public DefaultSqlSession(Configuration configuration, Executor executor) {
        this.configuration = configuration;
        this.executor = executor;
    }


    @Override
    public <T> T selectOne(String statement) {
        MappedStatement mappedStatement = configuration.getMappedStatement(statement);
        String sql = mappedStatement.getBoundSql().getSql();
        System.out.println("execute sql: " + sql);
        return null;
    }

    @Override
    public <T> T selectOne(String statement, Object params) {
        MappedStatement mappedStatement = configuration.getMappedStatement(statement);
        List<T> list = executor.query(mappedStatement, params);
        return list.get(0);
    }

    /**
     * ResultSet 转对象
     *
     * @param rs
     * @param clazz
     * @param <T>
     * @return
     */
    private <T> List<T> resultSetToObj(ResultSet rs, Class<?> clazz) throws Exception {
        List<T> resultList = new ArrayList<>();
        ResultSetMetaData metaData = rs.getMetaData();
        int columnCount = metaData.getColumnCount();
        T instance = (T) clazz.newInstance();
        while (rs.next()) {
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnName(i);
                String setMethodName = "set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);

                Object value = rs.getObject(i);
                Method method;
                if (value instanceof Timestamp) {
                    method = clazz.getMethod(setMethodName, Date.class);
                } else {
                    method = clazz.getMethod(setMethodName, value.getClass());
                }
                method.invoke(instance, value);
            }
            resultList.add(instance);
        }
        return resultList;
    }

    @Override
    public <T> T getMapper(Class<T> type) {
        return configuration.getMapper(type, this);
    }

    @Override
    public Configuration getConfiguration() {
        return this.configuration;
    }
}
